#ifndef _AGP_DATA_H_
#define _AGP_DATA_H_

#ifdef WIN32
#pragma warning(disable : 4786)
#endif

///////////////////////////////////////////////////////////////////////////////
#include <Point.h>
#include <Vector.h>
using namespace mathtool;

#include <string.h>
#include <list>
using namespace std;

class agp_vertex; //defined below

///////////////////////////////////////////////////////////////////////////////

struct agp_diagonal{
    agp_diagonal(const Point2d& p1, const Point2d& p2){ v[0]=p1; v[1]=p2; }
    Point2d v[2];
};

struct agp_line{
    agp_line(){ support=NULL; }
    Vector2d normal;
    Vector2d vec; //the vector along the line
    Point2d origin;
    agp_vertex * support;
};

/**
 * Vertex of polygon
 */
class agp_vertex
{
public:
    
    ///////////////////////////////////////////////////////////////////////////
    agp_vertex(){ init(); }
    agp_vertex( const Point2d& p ){ pos=p; init(); }
    ~agp_vertex();
    void setNext(agp_vertex * n){next=n; if(n!=NULL) n->pre=this; }
    void setPre(agp_vertex * n){pre=n; if(n!=NULL) n->next=this; }

    void computeNormal();
    
    ///////////////////////////////////////////////////////////////////////////
    void setPos(const Point2d& p) { pos=p; }
    const Point2d& getPos() const { return pos; }
    agp_vertex * getNext() const { return next; }
    agp_vertex * getPre() const { return pre; }
    const int& getID() const {return id;}
    //need this?
    const Vector2d& getNormal() const { return normal; }

private:

    void init(){
        next=pre=NULL; 
        id=++LAST_VID;
    }
    
    //basic info
    static int LAST_VID;
    int id;
    Point2d pos;      //position
    agp_vertex * next; //next reflexvertex in the polygon
    agp_vertex * pre;  //previous upvertex in the polygon

    Vector2d normal;  //normal, the segment normal from this v to the next.
};

/**
 * Polygon
 */
class agp_poly{

    friend class agp_2d;

public:

    enum POLYTYPE { UNKNOWN, PIN, POUT };

    ///////////////////////////////////////////////////////////////////////////
    agp_poly(POLYTYPE t){ head=NULL; type=t; }
    //agp_poly(const agp_poly& other);
    void destroy();

    ///////////////////////////////////////////////////////////////////////////
    // create agp_poly
    void beginPoly();
    void addVertex( double x, double y );
    void endPoly();

    ///////////////////////////////////////////////////////////////////////////
    // Access
    agp_vertex * getHead() const { return head; }
    POLYTYPE getType() const { return type; }
    void set(POLYTYPE t,agp_vertex * h){ 
        type=t; head=h; 
        if(h!=NULL){ tail=h->getPre(); }
        else{ tail=NULL; }
    }
    int getSize() const { return size; }
    ///////////////////////////////////////////////////////////////////////////
    // Operator

    //check if give poly line is the same as this
    bool operator==( const agp_poly& other ){ return other.head==head; }
    friend istream& operator>>( istream&, agp_poly& );
    friend ostream& operator<<( ostream&, const agp_poly& );

protected:

    ///////////////////////////////////////////////////////////////////////////
    void doInit(); /*return # of vertice in this poly*/

private:

    agp_vertex * head; //the head of vertex list
    agp_vertex * tail; //end of the vertex list
    int size;  //is this used???

    //In, out or unknow.
    POLYTYPE type;
};

#endif //
